home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / Open Transport / OT1.1 Developer Release / Open Transport SDK / Open Tpt Client Developer / Samples / Internet / OTMulticastPitchSample.cp < prev    next >
Encoding:
Text File  |  1996-11-19  |  10.2 KB  |  439 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        OTMulticastPitchSample.cp
  3.  
  4.     Contains:    IP Multicast under UDP sample.
  5.  
  6.     Copyright:    © 1993-1995 by Apple Computer, Inc., all rights reserved.
  7.  
  8. */
  9.  
  10. #ifndef __OPENTPTGLOBALNEW__
  11. #include <OpenTptGlobalNew.h>
  12. #endif
  13.  
  14. #include <OpenTptInternet.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <Quickdraw.h>
  18.  
  19. /*******************************************************************************
  20. ** Misc defines
  21. ********************************************************************************/
  22.  
  23. const UInt8        kDefaultTTL = 3;            // Normal IP multicast default is 1.
  24. const size_t    kMyPoolSize = 60000;
  25.  
  26.  
  27. /*******************************************************************************
  28. ** Globals
  29. ********************************************************************************/
  30.  
  31. char            gMulticastAddrStr[] = "235.1.2.3";
  32. InetPort        gMulticastPort = 2345;
  33. InetHost        gMulticastHost;
  34. InetAddress        gMulticastAddr;
  35. EndpointRef        gEndpt;
  36. char            gMessage[256];
  37.  
  38. /*******************************************************************************
  39. ** SetupMulticast
  40. ********************************************************************************/
  41.  
  42. OSStatus SetupMulticast()
  43. {
  44.     TEndpointInfo    info;
  45.     OSStatus        err = kOTNoError;
  46.     TBind            req;
  47.     InetAddress        myAddr;
  48.  
  49.     fprintf(stderr, "The program will send packets on port <%d>\n", gMulticastPort);
  50.  
  51.     do
  52.     {
  53.         //
  54.         //    Get a UDP endpoint which can be used for IP Multicast sends and receives
  55.         //
  56.         
  57.         gEndpt = OTOpenEndpoint(OTCreateConfiguration(kUDPName), 0, &info, &err);
  58.         if ( gEndpt == NULL || err != kOTNoError )
  59.         {
  60.             fprintf(stderr, "ERROR: OpenEndpoint(UDP) failed with error <%d>\n", err);
  61.             break;
  62.         }
  63.                 
  64.         //
  65.         //    Set up an Inet Address for the multicast group 
  66.         //    using our multicast address string and defined port number.
  67.         //
  68.         
  69.         OTInetStringToHost(gMulticastAddrStr, &gMulticastHost);
  70.         OTInitInetAddress(&gMulticastAddr, gMulticastPort, gMulticastHost);
  71.     
  72.         //
  73.         //    Do a normal bind to any IP address on our system,
  74.         //    but use the multicast port so we can receive loopbacks at times.
  75.         //    OK to use req for both input and output.
  76.         //
  77.         
  78.         OTInitInetAddress(&myAddr, gMulticastPort, 0);
  79.         req.addr.len = sizeof(myAddr);
  80.         req.addr.maxlen = sizeof(myAddr);
  81.         req.addr.buf = (unsigned char *) &myAddr;
  82.         err = gEndpt->Bind(&req, &req);
  83.         if ( err != kOTNoError )
  84.         {
  85.             fprintf(stderr, "ERROR: Bind() failed with error <%d>\n", err);
  86.             break;
  87.         }
  88.     
  89.         //
  90.         //    Let IP know to listen for this multicast IP address on all interfaces.
  91.         //    
  92.         
  93.         TOptMgmt             optReq;
  94.         UInt8                 optBuffer[ kOTOptionHeaderSize + sizeof(TIPAddMulticast) ];
  95.         TOption*             opt = (TOption*)optBuffer;
  96.         TIPAddMulticast*    addopt = (TIPAddMulticast*)opt->value; 
  97.         
  98.         optReq.flags = T_NEGOTIATE;
  99.         optReq.opt.len = sizeof(optBuffer);
  100.         optReq.opt.buf = (UInt8*) optBuffer;
  101.         
  102.         opt->level = INET_IP;
  103.         opt->name = IP_ADD_MEMBERSHIP;
  104.         opt->len = sizeof(optBuffer);
  105.         
  106.         addopt->multicastGroupAddress = gMulticastHost;
  107.         addopt->interfaceAddress = kOTAnyInetAddress;
  108.         
  109.         err = gEndpt->OptionManagement(&optReq, &optReq);
  110.         if ( err != kOTNoError )
  111.         {
  112.             fprintf(stderr, "ERROR: OTOptionManagement() (add membership) failed with %d\n", err);
  113.             break;
  114.         }
  115.     
  116.         //
  117.         //    Setup time-to-live for multicast sends (defaults to 1)
  118.         //    Can reuse the TOptMgmt, but not Option itself is different.
  119.         //    While we could reuse the buffer above, I'll do it right to 
  120.         //    demonstrate correctness.
  121.         //
  122.  
  123.         UInt8                 ttlOptBuffer[ kOTOneByteOptionSize ];
  124.         TOption*             ttlOpt = (TOption*)ttlOptBuffer;
  125.         
  126.         optReq.flags = T_NEGOTIATE;
  127.         optReq.opt.len = sizeof(ttlOptBuffer);
  128.         optReq.opt.buf = (UInt8*) ttlOptBuffer;
  129.         
  130.         ttlOpt->level = INET_IP;
  131.         ttlOpt->name = IP_MULTICAST_TTL;
  132.         ttlOpt->len = sizeof(ttlOptBuffer);
  133.         *(char*)(ttlOpt->value) = kDefaultTTL;
  134.         
  135.         err = gEndpt->OptionManagement(&optReq, &optReq);
  136.         if ( err != kOTNoError )
  137.         {
  138.             fprintf(stderr, "ERROR: OTOptionManagement() (set ttl) failed with %d\n", err);
  139.             break;
  140.         }
  141.         
  142.         //
  143.         //    Put the endpoint into nonblocking mode so we don't hang
  144.         //    when receiving messages in synchronous mode.
  145.         //
  146.         
  147.         err = gEndpt->SetNonBlocking();
  148.         if ( err != kOTNoError )
  149.         {
  150.             fprintf(stderr, "ERROR: SetNonBlocking() failed with %d\n", err);
  151.             break;
  152.         }
  153.     } while (false);
  154.     return ( err != kOTNoError );
  155. }
  156.  
  157. Boolean gLoopbackState = true;
  158.  
  159. void LoopbackToggle()
  160. {
  161.     OSStatus err;
  162.     
  163.     gLoopbackState = !gLoopbackState;
  164.     if ( gLoopbackState )
  165.         fprintf(stderr, "Loopback on\n");
  166.     else
  167.         fprintf(stderr, "Loopback off\n");
  168.  
  169.     //    
  170.     //    Turn off loopback - unless you want to receive your own packets back.
  171.     //
  172.  
  173.     TOptMgmt     optReq;
  174.     UInt8         optBuffer[ kOTOneByteOptionSize ];
  175.     TOption*    opt = (TOption*)optBuffer;
  176.     
  177.     optReq.flags     = T_NEGOTIATE;
  178.     optReq.opt.len     = sizeof(optBuffer);
  179.     optReq.opt.buf     = (UInt8*) optBuffer;
  180.     
  181.     opt->level             = INET_IP;
  182.     opt->name             = IP_MULTICAST_LOOP;
  183.     opt->len             = sizeof(optBuffer);
  184.     *(char *)(opt->value) = gLoopbackState;
  185.     
  186.     err = gEndpt->OptionManagement(&optReq, &optReq);
  187.     if ( err != kOTNoError )
  188.     {
  189.         fprintf(stderr, "ERROR: OTOptionManagement() (loopback toggle) failed with %d\n", err);
  190.     }
  191. }
  192.  
  193.  
  194. void Cleanup()
  195. {
  196.     gEndpt->Close();
  197. }
  198.  
  199. void RecvLoop()
  200. {
  201.     /* 
  202.      * This loop receives all messages waiting on the stream.
  203.      * It operates in synchronous but nonblocking mode.
  204.      * If there are no messages waiting, we go get another one to send.
  205.      * Loopback messages (when the toggle is one) will be received too.
  206.      */
  207.     
  208.     OSStatus    err;
  209.     TUnitData    unitdata;
  210.     InetAddress    addr;
  211.     OTFlags        flags;
  212.     char        remoteAddr[32];
  213.  
  214.     while (true)
  215.     {
  216.         memset(remoteAddr, 0, sizeof(remoteAddr));
  217.         memset(gMessage, 0, sizeof(gMessage));
  218.         unitdata.addr.maxlen = sizeof(addr);
  219.         unitdata.addr.buf = (unsigned char*) &addr;
  220.         unitdata.opt.maxlen = 0;
  221.         unitdata.opt.buf = 0;
  222.         unitdata.udata.maxlen = sizeof(gMessage);
  223.         unitdata.udata.buf = (UInt8*) gMessage;
  224.         err = gEndpt->RcvUData( &unitdata, &flags);
  225.         if ( err != kOTNoError )
  226.         {
  227.             if ( err == kOTNoDataErr )
  228.             {
  229.                 return;
  230.             }
  231.             else
  232.             {
  233.                 fprintf(stderr, "ERROR: RcvUData() failed with %d\n", err);
  234.                 break;
  235.             }
  236.         }
  237.         OTInetHostToString( addr.fHost, remoteAddr);
  238.         fprintf(stderr, "IP multicast from <%s>:%s\n", remoteAddr, gMessage);
  239.         fflush(stderr);
  240.     }
  241. }
  242.  
  243. void SendLoop()
  244. {
  245.     TUnitData    unitdata;
  246.     short        len;
  247.     Boolean        done = false;
  248.  
  249.     /* 
  250.      * This routine is a loop which will get one message for the user,
  251.      * send if via IP multicast, and then check for any received messages
  252.      * and print them out.
  253.      */
  254.     while ( !done )
  255.     {
  256.         memset(gMessage, 0, sizeof(gMessage));
  257.         fprintf(stderr, "Message to send (hit return to quit)?\n");
  258.         gets((char *) gMessage);
  259.         len = strlen((char *) gMessage);
  260.         if ( len != 0 )
  261.         {
  262.             unitdata.udata.len = len;
  263.             unitdata.udata.buf = (UInt8*) gMessage;
  264.             unitdata.opt.len = 0;
  265.             unitdata.opt.buf = NULL;
  266.             unitdata.addr.len = sizeof(gMulticastAddr);
  267.             unitdata.addr.buf = (unsigned char *)&gMulticastAddr;
  268.             gEndpt->SndUData( &unitdata);
  269.             RecvLoop();
  270.             LoopbackToggle();
  271.             fflush(stderr);
  272.         }
  273.         else
  274.             done = true;
  275.     }        
  276. }
  277.  
  278.  
  279. void ShowEndpointOptions()
  280. {
  281.     /*
  282.      *    This function retrieves and displays 
  283.      *    the IP and UDP endpoint options for this endpoint.
  284.      */
  285.      
  286.     OSStatus    err;
  287.     TOptMgmt*            ret = (TOptMgmt*)OTAlloc(gEndpt, T_OPTMGMT, T_OPT, &err);
  288.  
  289.     
  290.     do
  291.     {
  292.         fprintf(stderr, "Current Readable IP Option Settings for endpoint @ %08lX:\n", gEndpt);
  293.         if ( ret == NULL )
  294.         {
  295.             fprintf(stderr, "ERROR: could not allocate TOptMgmt structure (%d)\n", err);
  296.             break;
  297.         }
  298.         //
  299.         // Get the current IP options
  300.         //
  301.         TOptMgmt        req;
  302.         TOptionHeader    option;
  303.         
  304.         option.len        = kOTOptionHeaderSize;
  305.         option.level    = INET_IP;
  306.         option.name        = T_ALLOPT;
  307.         
  308.         req.opt.buf = (UInt8*)&option;
  309.         req.opt.len    = kOTOptionHeaderSize;
  310.         req.flags    = T_CURRENT;
  311.         
  312.         err = gEndpt->OptionManagement(&req, ret);
  313.         if ( err != kOTNoError )
  314.         {
  315.             fprintf(stderr, "ERROR: OptionManagement T_CURRENT request returned %d\n", err);
  316.             break;
  317.         }
  318.         //
  319.         // Now, let's print the options
  320.         //
  321.         {
  322.             TOption*    opt = (TOption*)ret->opt.buf;
  323.             char        string[512];
  324.  
  325.             err = OTCreateOptionString("ip", &opt, ret->opt.buf + ret->opt.len,
  326.                                        string, sizeof(string));
  327.             
  328.             if ( err == kOTNoError )
  329.             {
  330.                 char*    str = string;
  331.                 size_t    len = 0;
  332.                 while ( true )
  333.                 {
  334.                     char* temp = strchr(str, ',');
  335.                     if ( temp == NULL )
  336.                     {
  337.                         fprintf(stderr, "%s\n", str);
  338.                         break;
  339.                     }
  340.                     if ( len + temp - str + 1 > 80 )
  341.                     {
  342.                         fprintf(stderr, "\n");
  343.                         if ( *str == ' ' )
  344.                             str += 1;
  345.                         len = 0;
  346.                     }
  347.                     fprintf(stderr, "%*.*s", temp - str + 1, temp - str + 1, str);
  348.                     len += temp - str + 1;
  349.                     str = temp + 1;
  350.                 }
  351.             }
  352.         }
  353.         
  354.         TOption* opt =  OTFindOption(ret->opt.buf, ret->opt.len, INET_IP, IP_MULTICAST_TTL);
  355.             
  356.         if ( opt == NULL )
  357.             fprintf(stderr, "ERROR:OptionManagement did not have IP_MULTICAST_TTL in returned options\n");
  358.  
  359.         //
  360.         // Get the current UDP options
  361.         //
  362.         fprintf(stderr, "Current Readable UDP Option Settings for endpoint @ %08lX:\n", gEndpt);
  363.         option.len        = kOTOptionHeaderSize;
  364.         option.level    = INET_UDP;
  365.         option.name        = T_ALLOPT;
  366.         
  367.         req.opt.buf = (UInt8*)&option;
  368.         req.opt.len    = kOTOptionHeaderSize;
  369.         req.flags    = T_CURRENT;
  370.         
  371.         err = gEndpt->OptionManagement(&req, ret);
  372.         if ( err != kOTNoError )
  373.         {
  374.             fprintf(stderr, "ERROR: OptionManagement T_CURRENT request returned %d\n", err);
  375.             break;
  376.         }
  377.         //
  378.         // Now, let's print the options
  379.         //
  380.         {
  381.             TOption*    opt = (TOption*)ret->opt.buf;
  382.             char        string[512];
  383.  
  384.             err = OTCreateOptionString("udp", &opt, ret->opt.buf + ret->opt.len,
  385.                                        string, sizeof(string));
  386.             
  387.             if ( err == kOTNoError )
  388.             {
  389.                 char*    str = string;
  390.                 size_t    len = 0;
  391.                 while ( true )
  392.                 {
  393.                     char* temp = strchr(str, ',');
  394.                     if ( temp == NULL )
  395.                     {
  396.                         fprintf(stderr, "%s\n", str);
  397.                         break;
  398.                     }
  399.                     if ( len + temp - str + 1 > 80 )
  400.                     {
  401.                         fprintf(stderr, "\n");
  402.                         if ( *str == ' ' )
  403.                             str += 1;
  404.                         len = 0;
  405.                     }
  406.                     fprintf(stderr, "%*.*s", temp - str + 1, temp - str + 1, str);
  407.                     len += temp - str + 1;
  408.                     str = temp + 1;
  409.                 }
  410.             }
  411.         }
  412.         
  413.     } while ( false );
  414.     OTFree(ret, T_OPTMGMT);
  415. }
  416.  
  417.  
  418. void Inits()
  419. {
  420.     InitGraf(&qd.thePort);
  421.     if ( InitOpenTransport() != kOTNoError )
  422.     {
  423.         fprintf(stderr, "MulticastPitchSample: Could not initialize ASLM\n");
  424.         exit(1);
  425.     }
  426. }
  427.  
  428. void main()
  429. {
  430.     Inits();
  431.     if ( SetupMulticast() == kOTNoError )
  432.     {
  433.         ShowEndpointOptions();
  434.         SendLoop();
  435.         Cleanup();
  436.     }
  437. }
  438.  
  439.